home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
User's Choice Windows CD
/
User's Choice Windows CD (CMS Software)(1993).iso
/
misc2
/
ole_101.zip
/
PATRON.ZIP
/
OLEDOC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-13
|
10KB
|
379 lines
/*
* OLEDOC.C
*
* Constructor, Destructor, and utility functions for the DOCUMENT
* structure that contains document-related OLE information and a
* pointer to the document's OLESTREAM structure
*
* Copyright(c) Microsoft Corp. 1992 All Rights Reserved
*/
#include <windows.h>
#include <ole.h>
#include "oclient.h"
//Array of string pointers, global to OLE-specific code.
char NEAR *rgpszOLE[COLESTRINGS];
/*
* Memory containing the strings and a lock count. The first time
* PDocumentAllocate is called, we load the strings and increment the
* lock. For each PDocumentFree call we decrement the count. If it's
* decremented to zero we free the string memory.
*/
WORD cStringLock=0;
HANDLE hMemStrings;
/*
* PDocumentAllocate
*
* Purpose:
* Constructor method for the DOCUMENT data type. Allocates a DOCUMENT
* and sets the defaults in its fields:
* Initalize OLECLIENTVTBL and OLESTREAMVTBL
* Allocate and initialize an OLESTREAM structure (see OLESTREA.C)
* Register OLE clipboard formats
* Allocate scratch data and set pointers within it.
*
* Used from application initialization.
*
* Parameters:
* pfSuccess LPBOOL indicating if the initialization succeeded. If
* this function returns non-NULL, but *pfSuccess==FALSE,
* the caller must call the destructor function.
* hInst HANDLE of the application instance.
* pszCaption LPSTR to the application name.
* pfnCallBack FARPROC to the single client method to initialize.
* We pass this function to PVtblClientAllocate.
* pfnGet FARPROC to this document's Stream Get method.
* pfnPut FARPROC to this document's Stream Put method.
*
* Return Value:
* LPDOCUMENT Pointer to the allocated DOCUMENT if successful, NULL
* if the allocation failed or a parameter is invalid.
*/
LPDOCUMENT FAR PASCAL PDocumentAllocate(LPBOOL pfSuccess, HANDLE hInst,
LPSTR pszCaption, FARPROC pfnCallBack,
FARPROC pfnGet, FARPROC pfnPut)
{
LPDOCUMENT pDoc;
HANDLE hMem;
BOOL fTemp;
/*
* Any error condition will return FALSE unless we get all through
* this function. This scheme allows us to always return on any
* error instead of trying to clean up what was already initialized.
* Instead, we let the destructor, PDocumentFree, do the work.
*/
if (NULL==pfSuccess)
return NULL;
*pfSuccess=FALSE;
if (NULL==hInst || NULL==pszCaption)
return NULL;
//Allocate this structure.
hMem=LocalAlloc(LPTR, CBDOCUMENT);
if (NULL==hMem)
return NULL;
pDoc=(LPDOCUMENT)(PSTR)hMem;
/*
* The first time we allocate a DOCUMENT, load the strings and
* increment a counter. On subsequent DOCUMENT allocations, just
* copy the handle and increment the counter. The destructor
* function will decrement the counter and free the memory if
* the last DOCUMENT is freed.
*/
if (0==cStringLock)
{
hMemStrings=HLoadOLEStrings(hInst);
if (NULL==hMemStrings)
return pDoc;
}
cStringLock++;
//Save the document name
pDoc->aCaption=AddAtom(pszCaption);
//1. Register clipboard formats; the strings are globals in this file.
pDoc->cfNative =RegisterClipboardFormat(PSZOLE(IDS_NATIVE));
pDoc->cfOwnerLink =RegisterClipboardFormat(PSZOLE(IDS_OWNERLINK));
pDoc->cfObjectLink=RegisterClipboardFormat(PSZOLE(IDS_OBJECTLINK));
//Any error, return what we already allocated.
if (0==pDoc->cfNative || 0==pDoc->cfOwnerLink || 0==pDoc->cfObjectLink)
return pDoc;
//2. Get initialized OLECLIENTVTBL pointer.
pDoc->pvt=PVtblClientAllocate(&fTemp, hInst, pfnCallBack);
if (!fTemp)
return pDoc;
//3. Get an initialized STREAM pointer.
pDoc->pStream=PStreamAllocate(&fTemp, hInst, pfnGet, pfnPut);
if (!fTemp)
return pDoc;
//4. Allocate scratch memory.
pDoc->hData=GlobalAlloc(GHND, CSCRATCH*CBSCRATCH);
if (NULL==pDoc->hData)
return pDoc;
/*
* Initialize global pointers into this memory. Since we know we
* allocated with a nonzero byte count, GlobalLock will work.
*/
pDoc->pszData1=GlobalLock(pDoc->hData);
pDoc->pszData2=pDoc->pszData1+CBSCRATCH;
pDoc->pszData3=pDoc->pszData2+CBSCRATCH;
//Everything handled successfully.
*pfSuccess=TRUE;
return pDoc;
}
/*
* PDocumentFree
*
* Purpose:
* Frees all data in the DOCUMENT and frees the structure.
*
* Parameters:
* pDoc LPDOCUMENT to the structure to free.
*
* Return Value:
* LPDOCUMENT NULL if the function succeeds, pDoc otherwise.
*/
LPDOCUMENT FAR PASCAL PDocumentFree(LPDOCUMENT pDoc)
{
BOOL fRet=FALSE;
/*
* Free the scratch memory if we have any. No need to clear the
* pointers since we'll be freeing this structure anyway.
*/
if (NULL!=pDoc->hData)
GlobalFree(pDoc->hData);
if (pDoc->aCaption)
DeleteAtom(pDoc->aCaption);
//Free the stream we're holding
if (NULL!=PStreamFree(pDoc->pStream))
return pDoc;
//Free this object's VTBL
if (NULL!=PVtblClientFree(pDoc->pvt))
return pDoc;
if (NULL!=LocalFree((HANDLE)(DWORD)pDoc))
return pDoc;
//Free the strings if this was the only DOCUMENT around.
if (0==--cStringLock)
{
if (NULL!=hMemStrings)
LocalFree(hMemStrings);
}
return NULL;
}
/*
* FDocumentFileSet
*
* Purpose:
* Provides the document with an associated filename for use in
* OLE-related UI.
*
* Parameters:
* pDoc LPDOCUMENT in which to store the filename.
* pszFile LPSTR to the filename of the document.
*
* Return Value:
* BOOL TRUE if the function succeeds, FALSE otherwise.
*/
BOOL FAR PASCAL FDocumentFileSet(LPDOCUMENT pDoc, LPSTR pszFile)
{
if (NULL==pDoc || NULL==pszFile)
return FALSE;
if (pDoc->aFile)
DeleteAtom(pDoc->aFile);
pDoc->aFile=AddAtom(pszFile);
return TRUE;
}
/*
* PDocumentMsgProcSet
*
* Purpose:
* Informs the DOCUMENT structure about a function in the main application
* that translates and dispatches messages. This prevents the DOCUMENT
* from having to carry an accelerator handle or window handle and
* allows the application to perform other actions we cannot predict
* (like IsDialogMessage).
*
* Parameters:
* pDoc LPDOCUMENT to the structure concerned.
* pfn LPFNMSGPROC to the message processing function.
*
* Return Value:
* None
*/
void FAR PASCAL PDocumentMsgProcSet(LPDOCUMENT pDoc, LPFNMSGPROC pfn)
{
if (NULL!=pDoc)
pDoc->pfnMsgProc=pfn;
return;
}
/*
* PDocumentBackgroundProcSet
*
* Purpose:
* Informs the DOCUMENT structure about a function in the main application
* that performs background operations when there are no messages to
* process. This is necessary to provide a standard release waiting
* message loop such that that loop can call the background process
* function when it detects idle time.
*
* Parameters:
* pDoc LPDOCUMENT to the structure concerned.
* pfn LPFNMSGPROC to the background processing function.
*
* Return Value:
* None
*/
void FAR PASCAL PDocumentBackgroundProcSet(LPDOCUMENT pDoc, LPFNMSGPROC pfn)
{
if (NULL!=pDoc)
pDoc->pfnBackProc=pfn;
return;
}
/*
* HLoadOLEStrings
*
* Purpose:
* Allocates FIXED local memory and reads the applications
* string resources into that memory. Each string's pointer
* is available through the PSZOLE(i) macro where i is the ID
* value of the string. The strings must have sequential IDs.
*
* Note that string pointers are stored in the rgpszOLE global
* array defined in this file.
*
* Parameters:
* hInst HANDLE of the application instance.
*
* Return Value:
* HANDLE Handle to the local memory. NULL if memory could
* not be allocated.
*/
HANDLE PASCAL HLoadOLEStrings(HANDLE hInst)
{
HANDLE hMem;
char NEAR *pch;
WORD cchUsed=0;
WORD cch;
short i;
/*
* Allocate memory and load strings. NOTE! The LPTR style
* specifies FIXED memory. This should not be a big deal
* since this is an early allocation into the local heap.
* But it should be watched if the number of strings becomes
* large.
*/
hMem=LocalAlloc(LPTR, COLESTRINGS*CCHOLESTRINGMAX);
if (hMem==NULL)
return (HANDLE)NULL;
/*
* This operation is only valid for FIXED memory. Otherwise use
* LocalLock.
*/
pch=(char *)hMem;
/*
* Load the strings into the memory and retain the specific
* pointer to that string.
*/
for (i=IDS_OLEFIRST; i < IDS_OLELAST; i++)
{
cch=LoadString(hInst, i, (LPSTR)(pch+cchUsed), CCHOLESTRINGMAX-1);
PSZOLE(i)=(char *)(pch+cchUsed);
/*
* One is added to cch to include a NULL. The memory was ZEROINITed
* on allocation so by skipping a byte we get the NULL.
*/
cchUsed +=cch+1;
}
/*
* We are assuming that no string is over CCHSTRINGMAX, and therefore
* we did not use all the allocated memory. Therefore LocalReAlloc
* will only SHRINK the block, never expand it. So if it fails, we
* don't care--all the strings are still there, we just wasted some
* space.
*/
LocalReAlloc(hMem, cchUsed+1, LPTR);
return hMem;
}